(function () {

	function Game(boxObj) {
		this.box = boxObj;

		this.onReadyCallbacks = [];

		this.init();
	}

	Game.prototype.createStage = function (type) {
		var canvas = document.createElement('canvas');

		switch (type) {
			case 'main':
				canvas.width = GameSize.main.width;
				canvas.height = GameSize.main.height;
				canvas.className = 'game-main';
				break;

			case 'loading':
				canvas.width = GameSize.main.width;
				canvas.height = GameSize.main.height;
				canvas.className = 'game-loading';
				break;

			case 'roll':
				canvas.width = GameSize.roll.width;
				canvas.height = GameSize.roll.height;
				canvas.className = 'game-roll game-roll-' + arguments[1];
				break;
		}

		this.box.appendChild(canvas);
		return new createjs.Stage(canvas);
	};

	Game.prototype.init = function () {
		this.setState(GameState.LOADING);

		this.stages = {};
		this.stagesForTick = [];
		this.stages.loading = this.createStage('loading');
		this.stagesForTick.push(this.stages.loading);

		this.loading = new GameLoading(this.stages.loading);
		this.rollsNumber = 0;

		createjs.Ticker.addListener(this);
		createjs.Ticker.useRAF = true;
		createjs.Ticker.setFPS(30);

		var _this = this;
		this.loadResources(function () {
			_this.generateContent(function () {
				_this.show();
			});
		});
	};

	Game.prototype.loadResources = function (callback) {
		callback = callback || dummyFunction;

		var images = [
			'images/game_ims_bkg.jpg',
			'images/game_ims_payline_1.png',
			'images/game_ims_payline_2.png',
			'images/game_ims_payline_3.png',
			'images/game_ims_reels_blurred.png',
			'images/game_ims_a_symbol_animation.png',
			'images/game_ims_k_symbol_animation.png',
			'images/game_ims_q_symbol_animation.png',
			'images/game_ims_j_symbol_animation.png',
			'images/game_ims_10_symbol_animation.png',
			'images/game_ims_9_symbol_animation.png'
		];

		var loader = new PxLoader();

		for (var i = images.length; i--;) {
			loader.addImage(images[i]);
		}

		loader.addProgressListener(function (e) {
			window.console && window.console.log(e.completedCount + ' / ' + e.totalCount);
		});

		var _this = this;

		loader.addCompletionListener(function () {
			callback();
		});

		loader.start();
	};

	Game.prototype.generateContent = function (callback) {
		callback = callback || dummyFunction;
		var _this = this;

		this.stages.main = this.createStage('main');
		this.stagesForTick.push(this.stages.main);
		this.logo = new GameLogo(this.stages.main);

		this.bonusGameLogo = new BonusGameLogo(this.stages.main);

		this.rollsNumber = 5;
		this.rollElements = [GameElementJack, GameElementQueen, GameElementKing, GameElementAce];//, 'queen', 'king', 'ten', 'nine', 'jackpot', 'harp', 'scatter'];
		this.rolls = [];
		this.rollsSpinning = [];
		this.onRollSpinningStopCallback = function () {
			_this.onRollSpinningStop();
		};

		for (var i = this.rollsNumber; i--;) {
			var stage = this.createStage('roll', i);
			var roll = new GameRoll(stage, i, this.rollElements);
			this.stages['roll_' + i] = stage;
			this.stagesForTick.push(stage);
			this.rolls.push(roll);
		}

		if (true) {
			this.fpsDisplay = new createjs.Text('', '16px Arial', '#F00');
			this.fpsDisplay.y = 520;
			this.fpsDisplay.onTick = function () {
				this.text = createjs.Ticker.getMeasuredFPS().toFixed(0);
			};
			this.stages.main.addChild(this.fpsDisplay);
		}


		this.paylinesNames = [
			'left_4', 'left_2', 'left_6', 'left_8', 'left_1', 'left_9', 'left_7', 'left_3', 'left_5',
			'right_10', 'right_12', 'right_14', 'right_8', 'right_1', 'right_5', 'right_15', 'right_11', 'right_13'
		];
		this.paylines = [];
		for (var i = this.paylinesNames.length; i--;) {
			var name = this.paylinesNames[i];
			this.paylines[name] = new GamePayline(this.stages.main, name);
		}

		callback();
		return;

		// Paylines

		this.numberOfLinesMax = 3;
		this.numberOfLines = 2;
		this.numberOfLinesMin = 1;

		this.paylinesHighlitePeriod = 1000;
		this.paylinesNumber = this.paylinesNames.length;
		this.paylineHighliteDelay = Math.round(this.paylinesHighlitePeriod / this.paylinesNumber);


		// Payline maps

		this.paylineMaps = [];


//		this.denominationTable = new DenominationTable(this.numberOfLines);
//
//		this.bonusPointTable = new BonusPointTable(42051);


	};

	Game.prototype.show = function (state) {
		this.setState(GameState.LOADED);
	};

	Game.prototype.tick = function (state) {
		for (var i = this.stagesForTick.length; i--;) {
			this.stagesForTick[i].tick();
		}
	};

	Game.prototype.setState = function (state) {
		this.state = state;

		switch (state) {
			case GameState.LOADING:
				this.box.className = 'game-loading';
				break;

			case GameState.LOADED:
				for (var i = this.paylinesNames.length; i--;) {
					this.paylines[this.paylinesNames[i]].play();
				}
				this.setState(GameState.READY);
				break;

			case GameState.READY:
				this.box.className = 'game-ready';

				if (this.stages.loading) {
					this.box.removeChild(this.stages.loading.canvas);
					delete this.stages.loading;
					delete this.loading;
				}

				for (var i = 0, iLength = this.onReadyCallbacks.length; i < iLength; i++) {
					this.onReadyCallbacks[i]();
				}

				break;

			case GameState.PLAYING:
//				for (var i = 0, iLength = this.paylinesNames.length; i < iLength; i++) {
//					this.paylines[this.paylinesNames[i]].stop();
//				}
				break;
		}
	};

	Game.prototype.spin = function () {
		if (this.state != GameState.READY) {
			return;
		}

		this.setState(GameState.PLAYING);

		for (var i = this.rollsNumber; i--;) {
			this.rollsSpinning[i] = true;
			this.rolls[i].spin(this.onRollSpinningStopCallback);
		}
	};

	Game.prototype.onRollSpinningStop = function (rollNumber) {
		this.rollsSpinning[rollNumber] = false;

		for (var i = this.rollsNumber; i--;) {
			if (!this.rollsSpinning[i]) {
				// Not all spins are stopped
				return;
			}
		}

		this.setState(GameState.READY);
	};

	Game.prototype.onReady = function (callback) {
		if (typeof callback == 'function') {
			this.onReadyCallbacks.push(callback);
		}
	};

	/*

	 Game.prototype.generateContent = function () {
	 var _game = this;


	 //		var x = new GameElementJack();
	 //		x.play();
	 //		x.appendTo(this.stage);

	 return;

	 // Paylines


	 // Paylines maps
	 this.objPaylineMaps = $('<div/>').addClass('game-paylineMaps');
	 for (var i = 0; i < this.paylinesNumber; i++) {
	 var name = this.paylinesNames[i];
	 var paylineMap = new GamePaylineMap(name, this.rollsNumber);
	 this.objPaylineMaps.append(paylineMap.obj);
	 this.paylineMaps[name] = paylineMap;
	 }
	 this.obj.append(this.objPaylineMaps);

	 // Buttons
	 this.paytableButton = new GameButton('paytable', function () {
	 _game.startSpin();

	 window.setTimeout(function () {
	 _game.stopSpin();
	 }, _game.rollingPeriod);
	 });
	 this.obj.append(this.paytableButton.obj);

	 this.denominationIncButton = new GameButton('deniminationInc', function () {
	 _game.denominationInc();
	 });
	 this.obj.append(this.denominationIncButton.obj);

	 this.denominationDecButton = new GameButton('deniminationDec', function () {
	 _game.denominationDec();
	 });
	 this.obj.append(this.denominationDecButton.obj);

	 this.obj.append(this.denominationTable.obj);

	 this.obj.append(this.bonusPointTable.obj);
	 };

	 Game.prototype.show = function () {
	 this.setState('ready');


	 this.highlitePaylines();
	 this.showActiveLines(this.numberOfLines);
	 };




	 Game.prototype.showActiveLines = function () {
	 for (var i = 0; i < this.paylinesNumber; i++) {
	 var name = this.paylinesNames[i];
	 if (name <= this.numberOfLines) {
	 this.paylines[name].activate();
	 }
	 else {
	 this.paylines[name].deactivate();
	 }
	 }

	 this.numberOfLines == this.numberOfLinesMin ? this.denominationDecButton.disable() : this.denominationDecButton.enable();
	 this.numberOfLines == this.numberOfLinesMax ? this.denominationIncButton.disable() : this.denominationIncButton.enable();

	 this.denominationTable.Set(this.numberOfLines);
	 };

	 Game.prototype.showActiveLineMaps = function () {
	 for (var i = 0; i < this.paylinesNumber; i++) {
	 var name = this.paylinesNames[i];
	 if (name <= this.numberOfLines) {
	 this.paylineMaps[name].show();
	 }
	 else {
	 this.paylineMaps[name].hide();
	 }
	 }
	 };

	 Game.prototype.hideActiveLineMaps = function () {
	 for (var i = 0; i < this.paylinesNumber; i++) {
	 var name = this.paylinesNames[i];
	 this.paylineMaps[name].hide();
	 }
	 };


	 Game.prototype.startSpin = function () {
	 this.hideActiveLineMaps();
	 this.paytableButton.disable();

	 for (var i = 0; i < this.rollsNumber; i++) {
	 this.rolls[i].startSpin();
	 }
	 };

	 Game.prototype.stopSpin = function () {
	 for (var i = 0; i < this.rollsNumber; i++) {
	 this.rolls[i].stopSpin();
	 }

	 var spinResults = [];
	 for (var i = 0; i < this.rollsNumber; i++) {
	 spinResults.push(this.rolls[i].getContent());
	 }

	 for (var i = 1; i <= this.numberOfLines; i++) {
	 if (this.checkLine(i, spinResults)) {
	 this.paylineMaps[i].show();
	 }
	 }

	 this.paytableButton.enable();
	 };

	 Game.prototype.checkLine = function (paylineName, spinResults) {
	 switch (paylineName) {
	 case 1:
	 case 2:
	 case 3:
	 var rowNum = paylineName == 2 ? 0 : (paylineName == 1 ? 1 : 2);
	 var value = spinResults[0][rowNum];
	 for (var spinNum = 1, spinsLength = spinResults.length; spinNum < spinsLength; spinNum++) {
	 if (spinResults[spinNum][rowNum] != value) {
	 return false;
	 }
	 }

	 return true;
	 }
	 return false;
	 };

	 Game.prototype.denominationInc = function () {
	 switch (this.numberOfLines) {
	 case 1:
	 this.numberOfLines = 2;
	 break;
	 case 2:
	 this.numberOfLines = 3;
	 break;
	 case 3:
	 this.numberOfLines = 5;
	 break;
	 case 5:
	 this.numberOfLines = 7;
	 break;
	 }
	 this.showActiveLines();
	 this.showActiveLineMaps();
	 };

	 Game.prototype.denominationDec = function () {
	 switch (this.numberOfLines) {
	 case 2:
	 this.numberOfLines = 1;
	 break;
	 case 3:
	 this.numberOfLines = 2;
	 break;
	 case 5:
	 this.numberOfLines = 3;
	 break;
	 case 7:
	 this.numberOfLines = 5;
	 break;
	 }

	 this.showActiveLines();
	 this.showActiveLineMaps();
	 };

	 Game.prototype.startPaylinesHighlight = function () {
	 this.objPaylines.addClass('game-paylines-highlight');
	 };

	 Game.prototype.highlitePaylines = function () {
	 var _this = this;
	 for (var i = 0; i < this.paylinesNumber; i++) {
	 //			(function (i) {
	 //				window.setTimeout(function () {
	 var name = _this.paylinesNames[i];
	 _this.paylines[name].highliteOn(_this.paylineHighliteDelay);
	 //				}, i * _this.paylineHighliteDelay);
	 //			})(i);
	 }
	 };
	 */
	// #endregion

	window.onload = function () {
		game = new Game(document.getElementById('game'));
		document.getElementById('spinButton').onclick = function () {
			game.spin();
		};
	};
})
	();